﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using IPC.Communication.BasicFramework;
using IPC.Communication.Core;
using IPC.Communication.Core.Address;
using IPC.Communication.Core.IMessage;
using IPC.Communication.Core.Net;
using IPC.Communication.Reflection;

namespace IPC.Communication.Profinet.GE
{
    public class GeSRTPNet : NetworkDeviceBase
    {
        private SoftIncrementCount incrementCount = new SoftIncrementCount(65535L, 0L);

        public GeSRTPNet()
        {
            base.ByteTransform = new RegularByteTransform();
            base.WordLength = 2;
        }

        public GeSRTPNet(string ipAddress, int port = 18245)
            : this()
        {
            IpAddress = ipAddress;
            Port = port;
        }

        protected override INetMessage GetNewNetMessage()
        {
            return new GeSRTPMessage();
        }

        protected override OperateResult InitializationOnConnect(Socket socket)
        {
            OperateResult<byte[]> operateResult = ReadFromCoreServer(socket, new byte[56]);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            return OperateResult.CreateSuccessResult();
        }

        //[AsyncStateMachine(typeof(<InitializationOnConnectAsync>d__4))]
        //[DebuggerStepThrough]
        //protected override Task<OperateResult> InitializationOnConnectAsync(Socket socket)
        //{
        //    <InitializationOnConnectAsync>d__4 stateMachine = new <InitializationOnConnectAsync>d__4();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.socket = socket;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi("ReadByteArray", "")]
        public override OperateResult<byte[]> Read(string address, ushort length)
        {
            OperateResult<byte[]> operateResult = GeHelper.BuildReadCommand(incrementCount.GetCurrentValue(), address, length, isBit: false);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return GeHelper.ExtraResponseContent(operateResult2.Content);
        }

        [HslMqttApi("WriteByteArray", "")]
        public override OperateResult Write(string address, byte[] value)
        {
            OperateResult<byte[]> operateResult = GeHelper.BuildWriteCommand(incrementCount.GetCurrentValue(), address, value);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return GeHelper.ExtraResponseContent(operateResult2.Content);
        }

        [HslMqttApi("ReadByte", "")]
        public OperateResult<byte> ReadByte(string address)
        {
            OperateResult<GeSRTPAddress> operateResult = GeSRTPAddress.ParseFrom(address, 1, isBit: true);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte>(operateResult);
            }
            if (operateResult.Content.DataCode == 10 || operateResult.Content.DataCode == 12 || operateResult.Content.DataCode == 8)
            {
                return new OperateResult<byte>(StringResources.Language.GeSRTPNotSupportByteReadWrite);
            }
            return ByteTransformHelper.GetResultFromArray(Read(address, 1));
        }

        [HslMqttApi("WriteByte", "")]
        public OperateResult Write(string address, byte value)
        {
            OperateResult<GeSRTPAddress> operateResult = GeSRTPAddress.ParseFrom(address, 1, isBit: true);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<byte>(operateResult);
            }
            if (operateResult.Content.DataCode == 10 || operateResult.Content.DataCode == 12 || operateResult.Content.DataCode == 8)
            {
                return new OperateResult<byte>(StringResources.Language.GeSRTPNotSupportByteReadWrite);
            }
            return Write(address, new byte[1]
		{
			value
		});
        }

        [HslMqttApi("ReadBoolArray", "")]
        public override OperateResult<bool[]> ReadBool(string address, ushort length)
        {
            OperateResult<GeSRTPAddress> operateResult = GeSRTPAddress.ParseFrom(address, length, isBit: true);
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult);
            }
            OperateResult<byte[]> operateResult2 = GeHelper.BuildReadCommand(incrementCount.GetCurrentValue(), operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult2);
            }
            OperateResult<byte[]> operateResult3 = ReadFromCoreServer(operateResult2.Content);
            if (!operateResult3.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult3);
            }
            OperateResult<byte[]> operateResult4 = GeHelper.ExtraResponseContent(operateResult3.Content);
            if (!operateResult4.IsSuccess)
            {
                return OperateResult.CreateFailedResult<bool[]>(operateResult4);
            }
            return OperateResult.CreateSuccessResult(operateResult4.Content.ToBoolArray().SelectMiddle(operateResult.Content.AddressStart % 8, length));
        }

        [HslMqttApi(ApiTopic = "WriteBoolArray", Description = "In units of bits, write bool arrays in batches to the specified addresses")]
        public override OperateResult Write(string address, bool[] value)
        {
            OperateResult<byte[]> operateResult = GeHelper.BuildWriteCommand(incrementCount.GetCurrentValue(), address, value);
            if (!operateResult.IsSuccess)
            {
                return operateResult;
            }
            OperateResult<byte[]> operateResult2 = ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return operateResult2;
            }
            return GeHelper.ExtraResponseContent(operateResult2.Content);
        }

        //[AsyncStateMachine(typeof(<ReadAsync>d__11))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult<byte[]>> ReadAsync(string address, ushort length)
        //{
        //    <ReadAsync>d__11 stateMachine = new <ReadAsync>d__11();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__12))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult> WriteAsync(string address, byte[] value)
        //{
        //    <WriteAsync>d__12 stateMachine = new <WriteAsync>d__12();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadByteAsync>d__13))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<byte>> ReadByteAsync(string address)
        //{
        //    <ReadByteAsync>d__13 stateMachine = new <ReadByteAsync>d__13();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<byte>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__14))]
        //[DebuggerStepThrough]
        //public Task<OperateResult> WriteAsync(string address, byte value)
        //{
        //    <WriteAsync>d__14 stateMachine = new <WriteAsync>d__14();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadBoolAsync>d__15))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult<bool[]>> ReadBoolAsync(string address, ushort length)
        //{
        //    <ReadBoolAsync>d__15 stateMachine = new <ReadBoolAsync>d__15();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<bool[]>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.length = length;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<WriteAsync>d__16))]
        //[DebuggerStepThrough]
        //public override Task<OperateResult> WriteAsync(string address, bool[] value)
        //{
        //    <WriteAsync>d__16 stateMachine = new <WriteAsync>d__16();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.address = address;
        //    stateMachine.value = value;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        [HslMqttApi(Description = "Read the current time of the PLC")]
        public OperateResult<DateTime> ReadPLCTime()
        {
            OperateResult<byte[]> operateResult = GeHelper.BuildReadCoreCommand(incrementCount.GetCurrentValue(), 37, new byte[5]
		{
			0,
			0,
			0,
			2,
			0
		});
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<DateTime>(operateResult);
            }
            OperateResult<byte[]> operateResult2 = ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return OperateResult.CreateFailedResult<DateTime>(operateResult2);
            }
            OperateResult<byte[]> operateResult3 = GeHelper.ExtraResponseContent(operateResult2.Content);
            if (!operateResult3.IsSuccess)
            {
                return OperateResult.CreateFailedResult<DateTime>(operateResult3);
            }
            return GeHelper.ExtraDateTime(operateResult3.Content);
        }

        [HslMqttApi(Description = "Read the name of the current program of the PLC")]
        public OperateResult<string> ReadProgramName()
        {
            OperateResult<byte[]> operateResult = GeHelper.BuildReadCoreCommand(incrementCount.GetCurrentValue(), 1, new byte[5]
		{
			0,
			0,
			0,
			2,
			0
		});
            if (!operateResult.IsSuccess)
            {
                return OperateResult.CreateFailedResult<string>(operateResult);
            }
            OperateResult<byte[]> operateResult2 = ReadFromCoreServer(operateResult.Content);
            if (!operateResult2.IsSuccess)
            {
                return OperateResult.CreateFailedResult<string>(operateResult2);
            }
            OperateResult<byte[]> operateResult3 = GeHelper.ExtraResponseContent(operateResult2.Content);
            if (!operateResult3.IsSuccess)
            {
                return OperateResult.CreateFailedResult<string>(operateResult3);
            }
            return GeHelper.ExtraProgramName(operateResult3.Content);
        }

        //[AsyncStateMachine(typeof(<ReadPLCTimeAsync>d__19))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<DateTime>> ReadPLCTimeAsync()
        //{
        //    <ReadPLCTimeAsync>d__19 stateMachine = new <ReadPLCTimeAsync>d__19();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<DateTime>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        //[AsyncStateMachine(typeof(<ReadProgramNameAsync>d__20))]
        //[DebuggerStepThrough]
        //public Task<OperateResult<string>> ReadProgramNameAsync()
        //{
        //    <ReadProgramNameAsync>d__20 stateMachine = new <ReadProgramNameAsync>d__20();
        //    stateMachine.<>t__builder = AsyncTaskMethodBuilder<OperateResult<string>>.Create();
        //    stateMachine.<>4__this = this;
        //    stateMachine.<>1__state = -1;
        //    stateMachine.<>t__builder.Start(ref stateMachine);
        //    return stateMachine.<>t__builder.Task;
        //}

        public override string ToString()
        {
            return String.Format("GeSRTPNet[{0}:{1}]", IpAddress, Port);
        }
    }
}
